package cn.assumejson.springframework.beans.factory.support;

import cn.assumejson.springframework.beans.PropertyValues;
import cn.assumejson.springframework.beans.factory.BeansException;
import cn.assumejson.springframework.beans.factory.config.BeanDefinition;
import cn.assumejson.springframework.beans.factory.config.ConfigurableBeanFactory;

/**
 * @Author Mr. Li
 * @Date 2021/11/29 22:54
 * @Version 1.0
 */
public abstract class AbstractBeanDefinition implements BeanDefinition {

    /**
     * 考虑到Bean的生命周期，Object 在Bean没有被实例化之前都将是一个class对象的全限定名
     */
    private volatile Object beanClass;

    /**
     * 参数描述器
     */
    private PropertyValues propertyValues;

    /**
     * 初始化函数
     */
    private String initMethodName;

    /**
     * 销毁函数
     */
    private String destroyMethodName;

    private String scope = ConfigurableBeanFactory.SCOPE_SINGLETON;

    private boolean lazyInit = false;

    private String singleton = BeanDefinition.SCOPE_SINGLETON;

    public AbstractBeanDefinition(PropertyValues propertyValues) {
        this.propertyValues = propertyValues;
    }

    public AbstractBeanDefinition() {
    }

    public void setInitMethodName(String initMethodName) {
        this.initMethodName = initMethodName;
    }

    /**
     * Return the name of the initializer method.
     */
    public String getInitMethodName() {
        return this.initMethodName;
    }

    @Override
    public boolean isSingleton() {
        return BeanDefinition.SCOPE_SINGLETON.equals(scope);
    }

    public String getDestroyMethodName() {
        return destroyMethodName;
    }

    public void setDestroyMethodName(String destroyMethodName) {
        this.destroyMethodName = destroyMethodName;
    }

    @Override
    public PropertyValues getPropertyValues() {
        return propertyValues;
    }

    @Override
    public void setBeanClassName(String beanClassName) {
        this.beanClass = beanClassName;
    }

    public void setBeanClass(Object beanClass) {
        this.beanClass = beanClass;
    }

    @Override
    public Class<?> getBeanClass() {
        if (!(beanClass instanceof String)) {
            return (Class<?>) beanClass;
        }
        Class<?> bean = null;
        try {
            bean = Class.forName((String) beanClass);
        } catch (ClassNotFoundException e) {
            throw new BeansException("getBeanClass is fail");
        }
        return bean;
    }

    @Override
    public String getBeanClassName() {
        Object beanClassName = this.beanClass;
        // 判断当前bean是class 还是全限定名
        if (beanClassName instanceof Class) {
            return ((Class<?>) beanClassName).getName();
        }
        return (String) beanClassName;
    }

    @Override
    public void setScope(String scope) {
        this.scope = scope;
    }

    @Override
    public String getScope() {
        return this.scope;
    }

    @Override
    public void setLazyInit(boolean lazyInit) {
        this.lazyInit = lazyInit;
    }

    @Override
    public boolean isLazyInit() {
        return this.lazyInit;
    }

    @Override
    public Object getBean() throws BeansException {
        Object bean = null;
        if (beanClass instanceof Class) {
            try {
                bean = ((Class<?>) beanClass).newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
            }
        } else {
            try {
                bean = Class.forName(getBeanClassName());
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return bean;
    }

}
